package cn.zglbk.utils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 猪哥亮
 * 检查-转换反射类型
 */
public class TypeUtils {
    private static final Logger logger = LoggerFactory.getLogger(TypeUtils.class);
    private static final Map<Class<?>, Class<?>> EIB_PRIMITIVR = new HashMap<>();
    static {
        EIB_PRIMITIVR.put(int.class,int.class);
        EIB_PRIMITIVR.put(long.class,long.class);
        EIB_PRIMITIVR.put(byte.class,byte.class);
        EIB_PRIMITIVR.put(short.class,short.class);
        EIB_PRIMITIVR.put(char.class,char.class);
        EIB_PRIMITIVR.put(float.class,float.class);
        EIB_PRIMITIVR.put(double.class,double.class);
        EIB_PRIMITIVR.put(boolean.class,boolean.class);

        EIB_PRIMITIVR.put(Integer.class, Integer.class);
        EIB_PRIMITIVR.put(Long.class, Long.class);
        EIB_PRIMITIVR.put(Byte.class, Byte.class);
        EIB_PRIMITIVR.put(Short.class, Short.class);
        EIB_PRIMITIVR.put(Character.class, Character.class);
        EIB_PRIMITIVR.put(Float.class, Float.class);
        EIB_PRIMITIVR.put(Double.class, Double.class);
        EIB_PRIMITIVR.put(Boolean.class, Boolean.class);
        EIB_PRIMITIVR.put(String.class, String.class);
    }
    /**
     * 是否是基本数据类型
     * 注 ： 这里将包装类和String也纳入进来
     * @param clazz
     * @return
     */
    public static boolean isPrimitive(Class<?> clazz){
        return EIB_PRIMITIVR.containsKey(clazz);
    }
    public static boolean isPrimitive(String t) {
        boolean b = false;
        switch (t) {
            case "java.lang.String":
                b = true;
                break;
            case "java.lang.Double":
                b = true;
                break;
            case "java.lang.Boolean":
                b = true;
                break;
            case "java.lang.Short":
                b = true;
                break;
            case "java.lang.Byte":
                b = true;
                break;
            case "java.lang.Float":
                b = true;
                break;
            case "java.lang.Long":
                b = true;
                break;
            case "java.lang.Char":
                b = true;
                break;
            case "java.lang.Integer":
                b = true;
                break;

            case "String":
                b = true;
                break;
            case "double":
                b = true;
                break;
            case "boolean":
                b = true;
                break;
            case "short":
                b = true;
                break;
            case "byte":
                b = true;
                break;
            case "float":
                b = true;
                break;
            case "long":
                b = true;
                break;
            case "char":
                b = true;
                break;
            case "int":
                b = true;
                break;
            default:
                b = false;
        }
        return b;
    }
    /**
     * 根据类型获取该生成的类型
     *
     * @param t
     * @return
     */
    public static String getArrType(String t, String beanName, String fieldName) {
        String type = "";
        switch (t) {
            case "java.lang.String":
                type = "string";
                break;
            case "java.lang.Double":
                type = "double";
                break;
            case "java.lang.Boolean":
                type = "bool";
                break;
            case "java.lang.Short":
                type = "short";
                break;
            case "java.lang.Byte":
                type = "byte";
                break;
            case "java.lang.Float":
                type = "float";
                break;
            case "java.lang.Long":
                type = "long";
                break;
            case "java.lang.Char":
                type = "char";
                break;
            case "java.lang.Integer":
                type = "int";
                break;

            case "String":
                type = "string";
                break;
            case "double":
                type = "double";
                break;
            case "boolean":
                type = "bool";
                break;
            case "short":
                type = "short";
                break;
            case "byte":
                type = "byte";
                break;
            case "float":
                type = "float";
                break;
            case "long":
                type = "long";
                break;
            case "char":
                type = "char";
                break;
            case "int":
                type = "int";
                break;
            default:
                type = StringUtils.substringAfterLast(t, ".");
        }
        if (StringUtils.isBlank(type)) {
            type = "Object";
            logger.error("对象"+beanName+"的"+fieldName+"变量的类型属性"+t+"不正确：反射数据类型异常将自动转为string类型");
        }
        return type;
    }
    public static String getArrType1(String t, String beanName, String fieldName) {
        String type = "";
        switch (t) {
            case "java.lang.String":
                type = "string";
                break;
            case "java.lang.Double":
                type = "double";
                break;
            case "java.lang.Boolean":
                type = "bool";
                break;
            case "java.lang.Short":
                type = "short";
                break;
            case "java.lang.Byte":
                type = "byte";
                break;
            case "java.lang.Float":
                type = "float";
                break;
            case "java.lang.Long":
                type = "int64";
                break;
            case "java.lang.Char":
                type = "char";
                break;
            case "java.lang.Integer":
                type = "int32";
                break;
            case "java.util.Date":
                type = "int64";
                break;
            case "String":
                type = "string";
                break;
            case "double":
                type = "double";
                break;
            case "boolean":
                type = "bool";
                break;
            case "short":
                type = "short";
                break;
            case "byte":
                type = "byte";
                break;
            case "float":
                type = "float";
                break;
            case "long":
                type = "int64";
                break;
            case "char":
                type = "char";
                break;
            case "int":
                type = "int32";
                break;
            default:
                type = StringUtils.substringAfterLast(t, ".");
        }
        if (StringUtils.isBlank(type)) {
            type = "Object";
            logger.error("对象"+beanName+"的"+fieldName+"变量的类型属性"+t+"不正确：反射数据类型异常将自动转为string类型");
        }
        return type;
    }
    public static String checkProtocolType(String str, String clazz) {
        String type = "";
        switch (str) {
            case "boolean":
                type = "Boolean.parseBoolean";
                break;
            case "bool":
                type = "Boolean.parseBoolean";
                break;
            case "int":
                type = "Integer.parseInt";
                break;
            case "short":
                type = "Short.parseShort";
                break;
            case "byte":
                type = "Byte.parseByte";
                break;
            case "long":
                type = "Long.parseLong";
                break;
            case "float":
                type = "Float.parseFloat";
                break;
            case "double":
                type = "Double.parseDouble";
                break;

            case "Bool":
                type = "Boolean.parseBoolean";
                break;
            case "Boolean":
                type = "Boolean.parseBoolean";
                break;
            case "Integer":
                type = "Integer.parseInt";
                break;
            case "Short":
                type = "Short.parseShort";
                break;
            case "Byte":
                type = "Byte.parseByte";
                break;
            case "Long":
                type = "Long.parseLong";
                break;
            case "Float":
                type = "Float.parseFloat";
                break;
            case "Double":
                type = "Double.parseDouble";
                break;

            default:
                type = "String";
                break;
        }
        if (StringUtils.isEmpty(type)) {
            logger.error("协议类"+clazz+"的"+str+"类型异常错误");
        }
        return type;
    }

    /**
     * 获取集合类型
     *
     * @param
     * @return
     */
    public static String getGather(Field ft, String beanName, String fieldName) {
        String type = "";
        switch (ft.getType().toString()) {
            case "interface java.util.List":
                String ty = getGatherType(false, ft.getGenericType(), beanName, fieldName);
                type = "List<" + ty + ">";
                break;
            case "interface java.util.Set":
                String ty1 = getGatherType(false, ft.getGenericType(), beanName, fieldName);
                type = "Set<" + ty1 + ">";
                break;
            case "interface java.util.Map":
                String ty2 = getGatherType(true, ft.getGenericType(), beanName, fieldName);
                type = "Dictionary<" + ty2 + ">";
                break;
            default:
                break;
        }
        if (StringUtils.isBlank(type)) {
            logger.error("反射数据类型异常");
        }
        return type;
    }
    public static String getGather1(Field ft, String beanName, String fieldName) {
        String type = "";
        switch (ft.getType().toString()) {
            case "interface java.util.List":
                String ty = getGatherType1(false, ft.getGenericType(), beanName, fieldName);
                type = "repeated " + ty + " ";
                break;
            case "interface java.util.Set":
                String ty1 = getGatherType1(false, ft.getGenericType(), beanName, fieldName);
                type = "repeated " + ty1 + " ";
                break;
            case "interface java.util.Map":
                String ty2 = getGatherType1(true, ft.getGenericType(), beanName, fieldName);
                type = "repeated " + ty2 + " ";
                break;
            default:
                break;
        }
        if (StringUtils.isBlank(type)) {
            logger.error("反射数据类型异常");
        }
        return type;
    }

    private static String getGatherType(boolean isMap, Type t, String beanName, String fieldName) {
        String type = "";
        ParameterizedType pt = (ParameterizedType) t;
        try {
            if (isMap) {
                Class<?> genericClazz = (Class) pt.getActualTypeArguments()[0];
                Class<?> genericClazz1 = (Class) pt.getActualTypeArguments()[1];
                String k = TypeUtils.getArrType(genericClazz.getName(), beanName, fieldName);
                String v = TypeUtils.getArrType(genericClazz1.getName(), beanName, fieldName);
                type = k + "," + v;
            } else {
                Class genericClazz = (Class) pt.getActualTypeArguments()[0];
                type = TypeUtils.getArrType(genericClazz.getName(), beanName, fieldName);
            }
            if (StringUtils.isBlank(type)) {
                logger.error("集合类型错误异常");
            }
        }catch (Exception e){
            logger.error(beanName + "  " +fieldName,e);
        }
        return type;
    }
    private static String getGatherType1(boolean isMap, Type t, String beanName, String fieldName) {
        String type = "";
        ParameterizedType pt = (ParameterizedType) t;
        try {
            if (isMap) {
                Class<?> genericClazz = (Class) pt.getActualTypeArguments()[0];
                Class<?> genericClazz1 = (Class) pt.getActualTypeArguments()[1];
                String k = TypeUtils.getArrType1(genericClazz.getName(), beanName, fieldName);
                String v = TypeUtils.getArrType1(genericClazz1.getName(), beanName, fieldName);
                type = k + "," + v;
            } else {
                Class genericClazz = (Class) pt.getActualTypeArguments()[0];
                type = TypeUtils.getArrType1(genericClazz.getName(), beanName, fieldName);
            }
            if (StringUtils.isBlank(type)) {
                logger.error("集合类型错误异常");
            }
        }catch (Exception e){
            logger.error(beanName + "  " +fieldName,e);
        }
        return type;
    }
    /**
     * 转换参数类型
     *
     * @param params
     * @param clazz
     * @return
     */
    public static Object stringToObject(Class<?> clazz, String params) {
        if (clazz.equals(int.class) || clazz.equals(Integer.class)) {
            return Integer.parseInt(params);
        } else if (clazz.equals(short.class) || clazz.equals(Short.class)) {
            return Short.parseShort(params);
        } else if (clazz.equals(byte.class) || clazz.equals(Byte.class)) {
            return Byte.parseByte(params);
        } else if (clazz.equals(boolean.class) || clazz.equals(Boolean.class)) {
            return Boolean.parseBoolean(params);
        } else if (clazz.equals(long.class) || clazz.equals(Long.class)) {
            return Long.parseLong(params);
        } else if (clazz.equals(float.class) || clazz.equals(Float.class)) {
            return Float.parseFloat(params);
        } else if (clazz.equals(double.class) || clazz.equals(Double.class)) {
            return Double.parseDouble(params);
        } else if (clazz.equals(String.class)) {
            return params;
        } else {
            return params;
        }
    }

    public static String typeStr(Field field, String beanName) {
        String typestr = "";
        //忽略生成字段
        Type isType = field.getGenericType();
        String fieldName = field.getName();
        //泛型类型
        if (isType instanceof ParameterizedType) {
            typestr = TypeUtils.getGather(field, beanName, fieldName);
            //数组
        } else if (field.getType().isArray()) {
            String arrFieldType = field.getGenericType().getTypeName();
            Class<?> arr = field.getType();
            arrFieldType = StringUtils.substringBeforeLast(arrFieldType, "[");
            typestr = TypeUtils.getArrType(arrFieldType, beanName, fieldName) + "[]";
        } else {
            Type type = field.getGenericType();
            typestr = TypeUtils.getArrType(type.getTypeName(), beanName, fieldName);
        }
        return typestr;
    }
    public static String typeStr1(Field field, String beanName) {
        String typestr = "";
        //忽略生成字段
        Type isType = field.getGenericType();
        String fieldName = field.getName();
        //泛型类型
        if (isType instanceof ParameterizedType) {
            typestr = getGather1(field, beanName, fieldName);
            //数组
        } else if (field.getType().isArray()) {
            String arrFieldType = field.getGenericType().getTypeName();
            arrFieldType = StringUtils.substringBeforeLast(arrFieldType, "[");
            typestr = "repeated "+getArrType1(arrFieldType, beanName, fieldName);
        } else {
            Type type = field.getGenericType();
            typestr = getArrType1(type.getTypeName(), beanName, fieldName);
        }
        return typestr;
    }
}